using System;
using System.Collections.Generic;
using System.Text;

namespace SQLString.Classes
{
	class StringManager
	{

		#region Prop Def

		//	the buffer holding the source string for processing
		private string szStringforeval = string.Empty;
		public string StringEvauation
		{
			get
			{
				return szStringforeval.Trim();
			}
			set
			{
				szStringforeval = value.Trim();
			}
		}
		//	User Charac wrap value
		private int iWrapValue;
		public int Wrap
		{
			get
			{
				return iWrapValue;
			}
			set
			{
				iWrapValue = value;
			}
		}
		//	Does the user want the Generated String in Upper Case
		private Boolean bToUpper = false;
		public Boolean UpperCase
		{
			get
			{
				return bToUpper;
			}
			set
			{
				bToUpper = value;
			}
		}
		//	Users Variable for the Generated String
		private string szUserVar = string.Empty;
		public string UserVariable
		{
			get
			{
				return szUserVar.Trim();
			}
			set
			{
				szUserVar = value.Trim();
			}
		}


		string sztLang = string.Empty;
		public string UserLanguage
		{
			get
			{
				return sztLang.Trim();
			}
			set
			{
				sztLang = value.Trim();
			}
		}

		string szDataType = string.Empty;
		public string UserDataType
		{
			get
			{
				return szDataType.Trim();
			}
			set
			{
				szDataType = value.Trim();
			}
		}

		#endregion







		/************************************************************************************************************************************
		*
		*	DEVELOPER Code Mind Dumps
		*	=========================
		*
		*	Date					Developer		
		*	06/30/2008				Jeff Hamlin/jeffrey.hamlin@gmail.com/this.notNULL@gmail.com
		*
		*	Code Mind Dump Name
		*	So this will the core processing class for SQLString.
		*
		*	Code Mind Dump Detail
		*	Basically, there is the Property with the String value for evaluation.
		*	Then we have the BUILDER string and the MAINLINE string.  
		*	The BUILDER STRING - its purpose is short lived, but essential.  She holds the intermediate string value
		*							until the string is reset by appending a "\n" to the end of it.
		*	The MAINLINE STRING	is the string the the BUILDER sets her values to.  It is intermediate, in that its lifetime
		*							is the duration of the execution of the method.  It is appended to each RESET CYCLE, with a new
		*							version of the BUILDER string.
		* 
		*	When the BUILDER gets to a certain length (> than the Wrap Property) it is appended with the newline character and reset.
		*	The value of BUILDER is set to the MAINLINE.  
		*	When the entire array storing the string has been processed, the MAINLINE is then appended to the property with the 
		*	MAINLINE also.  The last iteration of MAINLINE contains the last line built from processing.
		*
		************************************************************************************************************************************/

		/*************************************************************************************
		 * 
		 * What kind of string are we building, StringBuilder, StringBuffer or String
		 * Need some new variables:
		 * 
		 * 1.) A declarations variable to declare the variable type
		 * 2.) a prefix variable to hold the beginning.
		 * 3.) A middle type or SECONDARY prefix variable, depending on the user selection
		 * 4.) A rear-end, caboose variable.
		 * 
		 *	We also need a baby rules processor to make sure the user cannot pick variable types
		 *	of a language that do not exist, but that the rules can be updated by the user
		 *	if standards change.
		 * 
		 * If the option to place the generated code into Stored Procedures is considered, the 
		 * data is in the array.
		 * 
		 * **************************************************************************************/

		private const string cSharp = "c# .net";
		private const string cpp = "c++ (mfc/atl) .net";
		private const string java = "java";
		private const string cUnix = "ansi c";
		private const string msvb = "visual basic .net";

		/*	RULES Class designed and tested.  Will require further modification of the DB.  A new table will
		 * maintain the rules relationships between the data types and the languages.
		 * 
		 * It will be flexible, and expandible, not fixed.
		 * 07.06.08
		 */

		public bool ProcessSQL()
		{
			string szStringLine = string.Empty;
			string szBuilderString = string.Empty;


			string szUSRDECVar = string.Empty;	//	declarations variable
			string szUSRPREVar = string.Empty;	//	preprocessor-1
			string szUSRPREVar2 = string.Empty;	//	preprocessor-2	-> // secondary only works where initial lines and subsequent lines are different like in concat, not in append methods.
			string szUSRCaboose = string.Empty;	//	I like caboose!!

			switch (this.UserLanguage.ToLower().Trim())
			{
				case cSharp:	
					if (string.Compare(this.UserDataType, "StringBuilder") == 0)
					{
						szUSRDECVar = "System.Text.StringBuilder " + this.UserVariable + " = new System.Text.StringBuilder(" + this.StringEvauation.Length.ToString() + "," + this.StringEvauation.Length.ToString() + ");\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + ".Append(" + string.Format("\"");
						szUSRPREVar2 = this.UserVariable.Trim() + ".Append(" + string.Format("\"");
						//	Now the caboose, or tail end of the stringbuilder!!
						szUSRCaboose = string.Format("\"") + ");" + "\n";

					}
					else if (string.Compare(this.UserDataType, "String") == 0)
					{
						szUSRDECVar = "String " + this.UserVariable + " = string.Empty;\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + " = " + string.Format("\"");
						szUSRPREVar2 = this.UserVariable + " += " + string.Format("\"");
						// Caboose for string
						szUSRCaboose = string.Format("\"") + ";" + "\n";
					}
					break;
				case cpp:
					if (string.Compare(this.UserDataType, "StringBuilder") == 0)
					{
						szUSRDECVar = "System::Text::StringBuilder^ " + this.UserVariable + " = new System::Text::StringBuilder(" + this.StringEvauation.Length.ToString() + "," + this.StringEvauation.Length.ToString() + ");\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + ".Append(" + string.Format("\"");
						szUSRPREVar2 = this.UserVariable.Trim() + ".Append(" + string.Format("\"");
						//	Now the caboose, or tail end of the stringbuilder!!
						szUSRCaboose = string.Format("\"") + ");" + "\n";
					}
					else if (string.Compare(this.UserDataType, "String") == 0)
					{
						szUSRDECVar = "String^ " + this.UserVariable + ";\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + " = " + string.Format("\"");
						szUSRPREVar2 = this.UserVariable + " += " + string.Format("\"");
						// Caboose for string
						szUSRCaboose = string.Format("\"") + ";" + "\n";
					}
					break;
				case java:
					if (string.Compare(this.UserDataType, "StringBuffer") == 0)
					{
						szUSRDECVar = "StringBuffer " + this.UserVariable + " = new StringBuffer(" + this.StringEvauation.Length.ToString() + ");\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + ".append(" + string.Format("\"");
						szUSRPREVar2 = this.UserVariable.Trim() + ".append(" + string.Format("\"");
						//	Now the caboose, or tail end of the stringbuilder!!
						szUSRCaboose = string.Format("\"") + ");" + "\n";

					}
					if (string.Compare(this.UserDataType, "StringBuilder") == 0)
					{
						szUSRDECVar = "StringBuilder " + this.UserVariable + " = new StringBuilder(" + this.StringEvauation.Length.ToString() + "," + this.StringEvauation.Length.ToString() + ");\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + ".append(" + string.Format("\"");
						szUSRPREVar2 = this.UserVariable.Trim() + ".append(" + string.Format("\"");
						//	Now the caboose, or tail end of the stringbuilder!!
						szUSRCaboose = string.Format("\"") + ");" + "\n";

					}
					else if (string.Compare(this.UserDataType, "String") == 0)
					{
						szUSRDECVar = "String " + this.UserVariable + " = string.Empty;\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + " = " + string.Format("\"");
						szUSRPREVar2 = this.UserVariable + " += " + string.Format("\"");
						// Caboose for string
						szUSRCaboose = string.Format("\"") + ";" + "\n";
					}
					break;
				case cUnix:
					if (string.Compare(this.UserDataType, "String") == 0)
					{
						szUSRDECVar = "char[" + this.StringEvauation.Length.ToString() + "] " + this.UserVariable + ";\n\n";
						//	now pre processing section
						szUSRPREVar = "strcat(" + this.UserVariable + "," + string.Format("\"");
						szUSRPREVar2 = "strcat(" + this.UserVariable + "," + string.Format("\"");
						// Caboose for string
						szUSRCaboose = string.Format("\"") + ");" + "\n";
					}
					break;
				case msvb:
					if (string.Compare(this.UserDataType, "StringBuilder") == 0)
					{
						szUSRDECVar = "Dim " + this.UserVariable + " As New System.Text.StringBuilder(" + this.StringEvauation.Length.ToString() + "," + this.StringEvauation.Length.ToString() + ")\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + ".Append(" + string.Format("\"");
						szUSRPREVar2 = this.UserVariable.Trim() + ".Append(" + string.Format("\"");
						//	Now the caboose, or tail end of the stringbuilder!!
						szUSRCaboose = string.Format("\"") + ")" + "\n";

					}
					else if (string.Compare(this.UserDataType, "String") == 0)
					{
						szUSRDECVar = "Dim " + this.UserVariable + " As String = string.Empty\n\n";
						//	now pre processing section
						szUSRPREVar = this.UserVariable + " = " + string.Format("\"");
						szUSRPREVar2 = this.UserVariable + " &= " + string.Format("\"");
						// Caboose for string
						szUSRCaboose = string.Format("\"") + "\n";
					}
					break;
			}



			List<string> glLines = new List<string>();
			//Debug.Assert(string.IsNullOrEmpty(this.StringEvauation)==true, "String cannot be null");
			try
			{
				if (string.IsNullOrEmpty(this.StringEvauation) || this.Wrap == 0)
				{
					return false;
				}
				else if (string.IsNullOrEmpty(this.StringEvauation) == false && this.Wrap > 0)
				{
					//strip the CRLF first
					int iLine = 0;
					bool bLineOneProcessed = false;
					Int32 iChar = 0;
					StringEvauation = StringEvauation.Replace("\n", " ").Replace("\r", " ").Replace("\r\n", " ").Replace("\n\r", " ");

					if (this.UpperCase)//Did the user want the case of the source changed to upper?  Place option in for lower also.
					{
						this.StringEvauation = string.Format(StringEvauation).ToUpper();
					}
					//	place string into array
					string[] cARXParsedSRCS = StringEvauation.Split(" ".ToCharArray());
					szStringLine = string.Empty;


					szStringLine = szUSRDECVar;// + this.UserVariable;	//	New User Generated Start Line
					// now process the array
					foreach (string szCurrentWord in cARXParsedSRCS)
					{
						if (( szBuilderString.Length + szCurrentWord.Length ) >= this.Wrap && bLineOneProcessed == false)
						{
							//szBuilderString ;	//this logic is valid only for the first line of text
							szStringLine += szUSRPREVar + szBuilderString + szUSRCaboose;	//Construct the var in a temp string
							szBuilderString = string.Empty;	//set it to the return one, and reset.
							szBuilderString += szCurrentWord;			// now need to append the double quotes to the BUILDER beginning and end
							iChar = 0;
							bLineOneProcessed = true;
						}
						else
						{
							if (( szBuilderString.Length + szCurrentWord.Length ) > this.Wrap)
							{
								//	time for a CR, set it and append it to main string then reset the builder
								szStringLine += szUSRPREVar2 + szBuilderString + szUSRCaboose;	//	Beginning of a line with variable.
								szBuilderString = string.Empty;
								szBuilderString += szCurrentWord;		// dont want to loose the word we have from the array, so append it now to the reset builder string
								iChar = 0;
							}
							else
							{
								szBuilderString = szBuilderString + " " + szCurrentWord;	//	intermediate builder, constructs lines
							}
							iChar++;
						}
						iLine++;
					}

					szStringLine += szUSRPREVar2 + szBuilderString + szUSRCaboose;
					StringEvauation = szStringLine.TrimStart(); 
					return true;
				}
				return false;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
				return false;
			}
		}
	}
}
